﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace Misuzilla.Net.Irc
{
    /// <summary>
    /// 受信者に対して送信するメッセージを表すインターフェースです。
    /// </summary>
    public interface IReceiverMessage
    {
        String Receiver { get; set; }
    }

    /// <summary>
    /// チャンネルに対して送信するメッセージを表すインターフェースです。
    /// </summary>
    public interface IChannelMessage
    {
        String Channel { get; set; }
    }

    /// <summary>
    /// 内容を送信するメッセージを表すインターフェースです。
    /// </summary>
    public interface IContentMessage
    {
        String Content { get; set; }
    }

    /// <summary>
    /// 受信者に対して送信するメッセージを表すクラスです。
    /// </summary>
    public abstract class ReceiverMessage : IrcMessage, IReceiverMessage
    {
        public ReceiverMessage() { Initialize(); }
        public ReceiverMessage(String receiver) { Initialize(); Receiver = receiver; }

        private void SetReceivers()
        {
            Receivers = new Collection<String>(CommandParams[ReceiverParamIndex].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
        }

        protected virtual void Initialize()
        {
            Receivers = new Collection<string>();
            SetReceivers();
        }

        protected virtual Int32 ReceiverParamIndex { get { return 0; } }
        public virtual String Receiver
        {
            get { return String.Join(",", new List<String>(Receivers).ToArray()); }
            set { CommandParams[ReceiverParamIndex] = value; SetReceivers(); }
        }
        public virtual Collection<String> Receivers { get; private set; }
        public override String ToString()
        {
            if (SenderNick.Length == 0)
                return String.Format("{0}: {1}", Command, Receiver);
            else
                return String.Format("{0}: {1} - {2}", Command, SenderNick, Receiver);
        }
    }

    /// <summary>
    /// 内容を送信するメッセージを表すクラスです。
    /// </summary>
    public abstract class ContentMessage : IrcMessage, IContentMessage
    {
        public ContentMessage() { }
        public ContentMessage(String content) { Content = content; }
        protected virtual Int32 ContentParamIndex { get { return 0; } }
        public virtual String Content { get { return CommandParams[ContentParamIndex]; } set { CommandParams[ContentParamIndex] = value; } }

        public override String ToString()
        {
            return String.Format("{0}: {1} ({2})", Command, SenderNick, Content);
        }
    }

    /// <summary>
    /// 受信者に対して内容を送信するメッセージを表すクラスです。
    /// </summary>
    public abstract class ReceiverContentMessage : IrcMessage, IReceiverMessage, IContentMessage
    {
        public ReceiverContentMessage() { Initialize(); }
        public ReceiverContentMessage(String receiver, String content) : base() { Receiver = receiver; Content = content; Initialize(); }

        protected virtual void Initialize()
        {
            Command = IrcMessage.GetCommandNameByType(this.GetType());
            Receivers = new Collection<string>();
            SetReceivers();
        }

        protected virtual Int32 ContentParamIndex { get { return 1; } }
        protected virtual Int32 ReceiverParamIndex { get { return 0; } }
        public virtual String Content { get { return CommandParams[ContentParamIndex]; } set { CommandParams[ContentParamIndex] = value; } }
        public virtual String Receiver
        {
            get { return String.Join(",", new List<String>(Receivers).ToArray()); }
            set { CommandParams[ReceiverParamIndex] = value; SetReceivers(); }
        }
        public virtual Collection<String> Receivers { get; private set; }

        private void SetReceivers()
        {
            Receivers = new Collection<String>(CommandParams[ReceiverParamIndex].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
        }

        public override String ToString()
        {
            if (Sender.Length != 0)
                return String.Format("{0}: ({1}) [{2}] {3}", Command, SenderNick, Receiver, Content);
            else
                return String.Format("{0}: [{1}] {2}", Command, Receiver, Content);
        }
    }

    /// <summary>
    /// チャンネルに対して内容を送信するメッセージを表すクラスです。
    /// </summary>
    public abstract class ChannelContentMessage : ReceiverContentMessage, IChannelMessage
    {
        public ChannelContentMessage() { }
        public ChannelContentMessage(String channel, String content) : base(channel, content) { }
        protected override Int32 ReceiverParamIndex { get { return ChannelParamIndex; } }
        protected virtual Int32 ChannelParamIndex { get { return 0; } }
        public virtual String Channel { get { return Receiver; } set { Receiver = value; } }
        public virtual Collection<String> Channels { get { return Receivers; } }
    }
    
    /// <summary>
    /// チャンネルが対象のメッセージを表すクラスです。
    /// </summary>
    public abstract class ChannelMessage : ReceiverMessage, IChannelMessage
    {
        public ChannelMessage() { }
        public ChannelMessage(String channel) : base(channel) { }
        protected override Int32 ReceiverParamIndex { get { return ChannelParamIndex; } }
        protected virtual Int32 ChannelParamIndex { get { return 0; } }
        public virtual String Channel { get { return Receiver; } set { Receiver = value; } }
        public virtual Collection<String> Channels { get { return Receivers; } }
    }
}
